package com.xxpure.pair;

import com.xxpure.lvq.LVQInterface;
import com.xxpure.lvq.Pair;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;

public class LVQ<E,T> {


	private final ArrayList<Pair<E,T>> initialData;//初始数据 E为样本 二T为标记
	private final ArrayList<Pair<E,T>> samples;//原型向量
	private final double learningRate;//学习率
	private final Random random;

	public LVQ(ArrayList<Pair<E, T>> initialData, double learningRate, int k) {
		this.initialData = initialData;
		this.learningRate = learningRate;
		random = new Random();
		samples = getInitialSamples(k);
	}

	private ArrayList<Pair<E,T>> getInitialSamples(int k) {
		var sampleIndex = new HashSet<Integer>();
		var samples = new ArrayList<Pair<E,T>>();
		var randomSample = new Random();
		int res = 0;
		while (samples.size() < k) {
			while (sampleIndex.contains(res))
				res = randomSample.nextInt(k);

			samples.add(initialData.get(res));
			sampleIndex.add(res);
		}
		return samples;
	}

	public ArrayList<Pair<E,T>> nextSample(LVQInterface<E, T> compare) throws Exception {
		if(compare.isOver())
			throw new Exception("this sample is then best");
		var randSample = initialData.get(random.nextInt(initialData.size()));
		int minPos = 0, minDistance = 0xfffff;
		for (int i = 0; i < samples.size(); i ++) {
			int randomSampleDistance = compare.getDistance(randSample, samples.get(i));
			if (randomSampleDistance < minDistance) {
				minDistance = randomSampleDistance;
				minPos = i;
			}
		}
			if( samples.get(minPos).getMark().equals(randSample.getMark())){
				randSample.setMark(compare.add(randSample.getMark(), compare.mul(compare.sub(randSample.getMark(), samples.get(minPos).getMark())
				,learningRate)));
			}
			else
				randSample.setMark(compare.sub(randSample.getMark(), compare.mul(compare.sub(randSample.getMark(), samples.get(minPos).getMark())
						,learningRate)));
		return samples;
	}

}
